// Package tunnel 实现了内网穿透的隧道管理功能。
//
// 主要功能：
// - 隧道的创建、删除、查询（manager.go）
// - 隧道服务器的启动和连接管理（server.go）
// - HTTP请求的接收、转发、响应（request_handler.go）
// - 新分片流式传输协议（chunked_protocol.go）
// - 旧协议兼容处理（legacy_protocol.go）
// - 流式数据传输（streaming_handler.go）
// - 连接池和资源清理（connection_manager.go）
// - 响应数据写入（response_writer.go）
//
// 架构说明：
//
//	浏览器 → 服务端公共端口 → 隧道连接 → 客户端 → 目标服务
//	       ↑                              ↓
//	       └──────── 响应数据 ←───────────┘
//
// 分片协议（新）：
//   - HTTP_RESPONSE_START:requestID:statusCode:headerLength\r\n + headers
//   - HTTP_RESPONSE_CHUNK:requestID:chunkSize\r\n + chunk data (循环)
//   - HTTP_RESPONSE_END:requestID\r\n (成功)
//   - HTTP_RESPONSE_ERROR:requestID:errorLength\r\n + error message (失败)
//
// 请求取消机制：
//   - 服务端检测到浏览器断开时，发送 REQUEST_CANCEL:requestID\r\n
//   - 客户端收到后立即停止传输，关闭目标连接
package tunnel

import (
	"context"
	"internal-net-bridge-server/internal/tunnel/protocols/http"
	"net"
	"sync"
	"time"

	"internal-net-bridge-server/internal/models"
	"internal-net-bridge-server/internal/services"
	"internal-net-bridge-server/internal/tunnel/protocols/common"
)

// ResponseMetadata 响应元数据（客户端-服务端协同优化）
// 🔥 核心思想：客户端在发送响应前，先发送元数据
//   - 服务端根据真实响应大小动态调整传输策略
//   - 解决"小请求大响应"的阻塞问题（如视频请求）
type ResponseMetadata struct {
	Size        int64     // 响应大小（字节，来自Content-Length）
	ContentType string    // 内容类型（来自Content-Type）
	SpeedLimit  int64     // 动态计算的速度限制（字节/秒，0表示不限速）
	ReceivedAt  time.Time // 接收元数据的时间
}

// StreamingConnection 表示一个流式传输的客户端连接。
//
// 用于跟踪HTTP客户端（浏览器）连接的状态，支持连接复用和超时清理。
// 主要用于分片协议（HTTP_RESPONSE_START/CHUNK/END）的连接管理。
//
// 字段说明：
//   - Conn: 底层TCP连接（到浏览器的连接）
//   - StartTime: 连接建立时间
//   - LastUsed: 最后一次使用时间（用于空闲超时检测，默认5分钟）
//   - Ctx: 请求上下文，用于实时取消传输
//   - CancelFunc: 取消函数，当浏览器关闭连接时调用
//
// 使用场景：
//  1. 普通请求：使用requestID作为key存储
//  2. Range请求：使用conn.RemoteAddr().String()作为key，多个Range请求共享同一个连接
//
// 清理机制：
//   - 空闲超过5分钟自动清理
//   - 总时长超过30分钟自动清理
//   - 响应完成后不立即关闭，支持HTTP keep-alive
//   - 浏览器关闭连接时，通过Ctx实时取消HTTP/2传输（<100ms延迟）
type StreamingConnection struct {
	Conn       net.Conn           // 到浏览器的TCP连接
	StartTime  time.Time          // 连接建立时间
	LastUsed   time.Time          // 最后一次使用时间
	Ctx        context.Context    // 请求上下文（用于实时取消）
	CancelFunc context.CancelFunc // 取消函数（浏览器关闭时调用）
}

// ChunkData 表示响应数据的一个分片。
//
// 用于旧的分片协议（HTTP_CHUNK_PACKET）的数据重组。
// 新协议（HTTP_RESPONSE_CHUNK）不需要重组，直接流式转发。
//
// 字段说明：
//   - Index: 分片索引（从0开始）
//   - Data: 分片的原始数据
//   - IsLast: 是否是最后一个分片
//   - Timestamp: 接收时间戳
type ChunkData struct {
	Index     int       // 分片索引
	Data      []byte    // 分片数据
	IsLast    bool      // 是否最后一片
	Timestamp time.Time // 接收时间
}

// ResponseAssembly 用于旧协议的响应重组。
//
// 旧协议需要等待所有分片接收完毕后，重组成完整响应再发送。
// 新协议（HTTP_RESPONSE_START/CHUNK/END）采用流式转发，不需要重组。
//
// 字段说明：
//   - RequestID: 请求唯一标识
//   - Chunks: 分片数据映射（索引 -> 分片）
//   - TotalChunks: 总分片数（从最后一个分片的Index+1得出）
//   - ReceivedSize: 已接收的数据大小
//   - StartTime: 开始接收时间
//   - LastUpdate: 最后更新时间
//   - IsComplete: 是否接收完整
type ResponseAssembly struct {
	RequestID    string             // 请求ID
	Chunks       map[int]*ChunkData // 分片映射
	TotalChunks  int                // 总分片数
	ReceivedSize int64              // 已接收大小
	StartTime    time.Time          // 开始时间
	LastUpdate   time.Time          // 最后更新时间
	IsComplete   bool               // 是否完整
}

// NewChunkedResponse 用于新分片格式的响应管理（过渡格式）。
//
// 这是旧分片协议的一个改进版本，但仍然需要重组。
// 最新的 HTTP_RESPONSE_START/CHUNK/END 协议已经完全流式化，不再需要此结构。
//
// 保留此结构是为了向后兼容。
//
// 字段说明：
//   - RequestID: 请求唯一标识
//   - ResponseHeader: HTTP响应头（包括状态行和所有头部）
//   - ChunkData: 分片数据映射
//   - ReceivedChunks: 已接收的分片数量
//   - TotalSize: 总数据大小
//   - StartTime: 开始接收时间
//   - LastUpdate: 最后更新时间
//   - IsHeaderReceived: 是否已接收响应头
//   - IsComplete: 是否接收完整
type NewChunkedResponse struct {
	RequestID        string         // 请求ID
	ResponseHeader   []byte         // 响应头
	ChunkData        map[int][]byte // 分片数据
	ReceivedChunks   int            // 已接收分片数
	TotalSize        int64          // 总大小
	StartTime        time.Time      // 开始时间
	LastUpdate       time.Time      // 最后更新时间
	IsHeaderReceived bool           // 是否已接收响应头
	IsComplete       bool           // 是否完整
}

// TunnelManager 是隧道管理的核心结构。
//
// 负责管理所有隧道的生命周期、连接处理、协议解析、数据转发等。
//
// 核心组件说明：
//
// 1. 隧道映射：
//   - tunnels: 所有活跃隧道（tunnelID -> Tunnel）
//   - portMappings: 端口到隧道的映射（publicPort -> Tunnel）
//   - domainMappings: 域名到隧道的映射（domain -> Tunnel）
//
// 2. 连接管理：
//   - connectionMap: 客户端连接映射（requestID/connAddr -> StreamingConnection）
//   - responseAssembly: 旧协议的响应重组（requestID -> ResponseAssembly）
//   - newChunkedResponses: 过渡协议的响应管理（requestID -> NewChunkedResponse）
//
// 3. 并发控制：
//   - connMapMutex: 保护 connectionMap
//   - assemblyMutex: 保护 responseAssembly
//   - newChunkedMutex: 保护 newChunkedResponses
//   - mutex: 保护 tunnels、portMappings、domainMappings
//
// 4. 外部服务：
//   - tunnelService: 数据库服务（持久化隧道配置）
//   - dnsService: DNSPod服务（动态DNS解析）
//   - domainRouter: 域名路由服务（HTTP Host路由）
//   - streamingHandler: 流式传输处理器
//   - proxyAdapter: 代理适配器
//
// 5. 配置：
//   - tunnelPort: 隧道服务器监听端口（默认9000）
//
// 线程安全：
//   - 所有公共方法都是线程安全的
//   - 使用读写锁优化并发性能
//
// 生命周期：
//   - 创建: NewTunnelManager()
//   - 初始化: InitializeWithConfig()
//   - 启动: StartTunnelServer()
//   - 运行: 持续处理连接和数据
//   - 关闭: （通常随进程结束）
type TunnelManager struct {
	// ===== 隧道映射 =====
	tunnels        map[string]*models.Tunnel // tunnelID -> Tunnel
	portMappings   map[string]*models.Tunnel // publicPort -> Tunnel
	domainMappings map[string]*models.Tunnel // domain -> Tunnel

	// ===== 连接管理 =====
	connectionMap        map[string]*StreamingConnection // requestID/connAddr -> connection
	responseAssembly     map[string]*ResponseAssembly    // requestID -> response assembly (旧协议)
	newChunkedResponses  map[string]*NewChunkedResponse  // requestID -> chunked response (过渡协议)
	responseMetadata     map[string]*ResponseMetadata    // 🔥 响应元数据（客户端-服务端协同）
	rateLimiters         map[string]*common.RateLimiter  // 🔥 请求级别的限速器缓存（requestID -> RateLimiter）
	canceledRequests     map[string]bool                 // 🔥 已取消的请求ID集合（避免重复发送CANCEL）
	loggedWarnings       map[string]time.Time            // 🔥 已记录的警告（requestID -> 首次记录时间）
	unknownPacketCount   int64                           // 🔥 未知数据包计数器（日志优化）
	lastUnknownPacketLog time.Time                       // 🔥 上次未知数据包日志时间（日志优化）

	// ===== 并发控制 =====
	connMapMutex       sync.RWMutex // 连接映射锁
	assemblyMutex      sync.RWMutex // 分片重组锁
	newChunkedMutex    sync.RWMutex // 新分片格式锁
	mutex              sync.RWMutex // 隧道映射锁
	cancelMutex        sync.RWMutex // 取消请求锁
	logMutex           sync.RWMutex // 日志去重锁
	unknownPacketMutex sync.Mutex   // 🔥 未知数据包计数锁（日志优化）

	// ===== 配置 =====
	tunnelPort int // 隧道服务器端口

	// ===== 外部服务 =====
	tunnelService       *services.TunnelService  // 数据库服务
	dnsService          *services.DNSPodService  // DNS服务
	domainRouter        *services.DomainRouter   // 域名路由
	streamingHandler    interface{}                    // 流式传输处理器（TODO: 定义接口）
	proxyAdapter        interface{}                    // 代理适配器（TODO: 定义接口）
	quicServer          *QUICTunnelServer              // 🚀 QUIC服务器
	uploadCacheManager  *http.UploadCacheManager       // 🆕 上传缓存管理器

	// ===== 🔥 协议管理（抽象接口架构） =====
	protocolFactory   *ProtocolFactory           // 协议工厂
	protocolListeners map[string]interface{}     // tunnelID -> ProtocolListener（存储各协议监听器）
	listenerMutex     sync.RWMutex               // 监听器映射锁
	http2Handler      *http.HTTP2ResponseHandler // 🚀 HTTP/2响应处理器（混合模式）
}
